Skip to content

renderer: implement native sRGB support #1687

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

illwieckz
Copy link
Member

@illwieckz illwieckz commented Jun 25, 2025

Implement native sRGB support.

Obsoletes #1543:

It includes the commit from #1686:

This is based on an even older branch from 2019 as I initially tested native sRGB support before attempting to implement it in GLSL.

I rebased on current master and merged improvements from the srgb-naive branch as it implemented more corner cases than this one.

It still suffers from the problems I faced in 2019: 2D colors are wrong. I need help on that part.

@illwieckz illwieckz added A-Renderer T-Feature-Request Proposed new feature labels Jun 25, 2025
@illwieckz illwieckz force-pushed the illwieckz/srgb-native branch 2 times, most recently from c914db4 to ce0a6e3 Compare June 25, 2025 07:46
@illwieckz
Copy link
Member Author

Hmmm… I don't know where to write the line glEnable( GL_FRAMEBUFFER_SRGB );, should it be called at the beginning of every frame?.

@VReaperV
Copy link
Contributor

Hmmm… I don't know where to write the line glEnable( GL_FRAMEBUFFER_SRGB );, should it be called at the beginning of every frame?.

You only really need to call it once, it's global state and will affect all sRGB framebuffers.

@illwieckz
Copy link
Member Author

Which framebuffer should be sRGB there?

@@ -972,6 +981,11 @@ static void ParseTriangleSurface( dsurface_t* ds, drawVert_t* verts, bspSurface_

cv->verts[ i ].lightColor = Color::Adapt( verts[ i ].color );

if ( tr.worldLinearizeLightMap )
{
cv->verts[ i ].lightColor.ConvertFromSRGB();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be done for patch meshes as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may have forgotten patch meshes.

tr.worldLinearizeLightMap = true;
}

if ( sRGBcolor && sRGBtex )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason to keep separate parameters for sRGBcolor and sRGBtex if they only ever take effect if both are true?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are separate options in q3map2. In fact it is hardly meaningful to have one and not the other, so we may add an extra test printing a warning and decide to do something as a fallback.

@@ -707,6 +707,78 @@ void GL_VertexAttribPointers( uint32_t attribBits )
}
}

GLint GL_ToSRGB_( GLint internalFormat, bool isSRGB )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why this is not in tr_image.cpp? All of the call-sites seem to be there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be moved elsewhere indeed. I just put it there because that was some kind of GL helper.

}
}

GLint GL_ToSRGB( GLint internalFormat, bool isSRGB )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can just be one function rather than GL_ToSRGB() and GL_ToSRGB_().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be much more wordy. It was a single function in my original branch, but I split it to make it less wordy.

@@ -1761,6 +1761,11 @@ void Tess_ComputeColor( shaderStage_t *pStage )
{
rgb = Math::Clamp( RB_EvalExpression( &pStage->rgbExp, 1.0 ), 0.0f, 1.0f );

if ( tr.worldLinearizeTexture )
{
rgb = convertFromSRGB ( rgb );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this conversion be done with other colorGen_ts as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It has to be verified one by one. I went for the obvious ones first (and I'm even not 100% confident yet).

@illwieckz illwieckz force-pushed the illwieckz/srgb-native branch from ce0a6e3 to 387cac8 Compare June 30, 2025 17:41
@illwieckz
Copy link
Member Author

As a matter of fact, I have zero confidence this implementation is correct, unlike the GLSL alternative implementation.
I expect this to be wrong because I lack some understanding of how sRGB stuff are done the OpenGL way.

Said otherway, I know how to implement the whole computation myself in GLSL, but I don't know how to configure OpenGL to let it do the computation by itself without me writing the explicit computation.

The GLSL implementation is a math algorithm, the OpenGL implementation is a puzzle.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants